﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using UITheme = Wormhole.UI.Application.Theme.Theme;

namespace Wormhole.UI.Application.Controls
{
	/// <author>Rodney McKay</author>
	/// <date>27 March 2008</date>
	/// <summary>
	/// This control displayes a player's score.
	/// </summary>
	public partial class Score : UserControl
	{
		#region Properties

		#region Player Score
		private Engine.Player.Player _player;
		/// <summary>
		/// The game engine object holding the player score.
		/// </summary>
		public Engine.Player.Player Player
		{
			get
			{
				return this._player;
			}

			set
			{
				this._player = value;
				this._player.Score.ScoreChanged += new Wormhole.Engine.Player.Score.ScoreChangedDelegate(Score_ScoreChanged);
				this.DisplayPlayerInformation();
			}
		}
		#endregion

		#region Player Number
		private int _playerNumber;
		/// <summary>
		/// Is this player 1 or player 2, in the future more than 2 players could be supported.
		/// </summary>
		public int PlayerNumber 
		{
			get
			{
				return this._playerNumber;
			}

			set
			{
				this._playerNumber = value;		
				this.DisplayPlayerInformation();
			}
		}
		#endregion
		
		#endregion

		#region Constructor
		/// <summary>
		/// Initialize a default instance of the class.
		/// </summary>
		public Score()
		{
			InitializeComponent();

			this.PlayerNumber = 1;
		}
		#endregion

		#region Display Player Information
		/// <summary>
		/// Display the player information.
		/// </summary>
		public void DisplayPlayerInformation()
		{
			if (this.Player != null)
			{
				this.lblTitle.Content = this.Player.Name;

				// apply the player theme
				if (this.PlayerNumber == 1)
					this.ApplyPlayerTheme(UITheme.Player.Player1);
				else if (this.PlayerNumber == 2)
					this.ApplyPlayerTheme(UITheme.Player.Player2);

				this.DisplayScore();
			}
		}
		#endregion

		#region Apply Player Theme
		/// <summary>
		/// Apply the player theme.
		/// </summary>
		/// <param name="playerTheme">The theme to be applied</param>
		protected void ApplyPlayerTheme(UITheme.Player.IPlayer playerTheme)
		{
			this.lblTitle.Foreground = playerTheme.TitleBrush;
			this.gsTitle.Color = playerTheme.TitleColor;
			this.imgScore.Source = new BitmapImage(new Uri(playerTheme.ScoreImage, UriKind.Relative));
			this.imgPlayer.Source = new BitmapImage(new Uri(playerTheme.PlayerImage, UriKind.Relative));
		}
		#endregion

		#region Display Score
		/// <summary>
		/// Display the score stored in the engine onbject.
		/// </summary>
		protected void DisplayScore()
		{
			this.lblGlyphs.Content = string.Format("{0}/{1}", this.Player.Score.GlyphScore, this.Player.Score.GlyphTotal);
			this.lblExperience.Content = string.Format("{0}/{1}", this.Player.Score.ExperienceScore, this.Player.Score.VictoryTotal);
			this.lblVillian.Content = string.Format("{0}/{1}", this.Player.Score.VillianScore, this.Player.Score.VictoryTotal);
		}
		#endregion

		#region Event Handlers

		#region Score Changed
		/// <summary>
		/// Score changed event handler.
		/// </summary>
		private void Score_ScoreChanged()
		{
			this.Dispatcher.Invoke(
				DispatcherPriority.Normal,
				(System.Windows.Forms.MethodInvoker)delegate()
			{
				this.DisplayScore();
			});
		}
		#endregion

		#region Victory Set
		/// <summary>
		/// Set the victory score.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void victorySet_Click(object sender, RoutedEventArgs e)
		{
			this.GetVictoryScore();
		}
		#endregion

		#region Glyph
		/// <summary>
		/// Handle mouse clicks on the glyph score area.
		/// </summary>
		private void recGlyph_MouseDown(object sender, MouseButtonEventArgs e)
		{
			if (e.LeftButton == MouseButtonState.Pressed)
				this.IncreaseGlyphScore();
			else if (e.RightButton == MouseButtonState.Pressed)
				this.DecreaseGlyphScore();
		}

		/// <summary>
		/// Increase the glyph score by 1.
		/// </summary>
		private void glyphIncrease_Click(object sender, RoutedEventArgs e)
		{
			this.IncreaseGlyphScore();
		}

		/// <summary>
		/// Decrease the glyph score by 1.
		/// </summary>
		private void glyphDecrease_Click(object sender, RoutedEventArgs e)
		{
			this.DecreaseGlyphScore();
		}

		/// <summary>
		/// Get the new glyph score from the user.
		/// </summary>
		private void glyphSet_Click(object sender, RoutedEventArgs e)
		{
			this.GetGlyphScore();
		}
		#endregion

		#region Experience
		/// <summary>
		/// Handle mouse clicks in the experience score area.
		/// </summary>
		private void recExperience_MouseDown(object sender, MouseButtonEventArgs e)
		{
			if (e.LeftButton == MouseButtonState.Pressed)
				this.IncreaseExperienceScore();
			else if (e.RightButton == MouseButtonState.Pressed)
				this.DecreaseExperienceScore();
		}

		/// <summary>
		/// Increase the experience score by 1.
		/// </summary>
		private void experienceIncrease_Click(object sender, RoutedEventArgs e)
		{
			this.IncreaseExperienceScore();
		}

		/// <summary>
		/// Decrease the experience score by 1.
		/// </summary>
		private void experienceDecrease_Click(object sender, RoutedEventArgs e)
		{
			this.DecreaseExperienceScore();
		}

		/// <summary>
		/// Allow the user to set the experience score.
		/// </summary>
		private void experienceSet_Click(object sender, RoutedEventArgs e)
		{
			this.GetExperienceScore();
		}
		#endregion

		#region Villian
		/// <summary>
		/// Handle mouse clicks in the villian score area.
		/// </summary>
		private void recVillian_MouseDown(object sender, MouseButtonEventArgs e)
		{
			if (e.LeftButton == MouseButtonState.Pressed)
				this.IncreaseVillianScore();
			else if (e.RightButton == MouseButtonState.Pressed)
				this.DecreaseVillianScore();
		}

		/// <summary>
		/// Increase the villian score by 1.
		/// </summary>
		private void villianIncrease_Click(object sender, RoutedEventArgs e)
		{
			this.IncreaseVillianScore();
		}

		/// <summary>
		/// Decrease the villian score by 1.
		/// </summary>
		private void villianDecrease_Click(object sender, RoutedEventArgs e)
		{
			this.DecreaseVillianScore();
		}

		/// <summary>
		/// Allow the user to set the villian score.
		/// </summary>
		private void villianSet_Click(object sender, RoutedEventArgs e)
		{
			this.GetVillianScore();
		}
		#endregion

		#endregion

		#region Get Score
		/// <summary>
		/// Get a score from the user.
		/// </summary>
		/// <param name="prompt">The input promt.</param>
		/// <param name="errorMessage">The error to display when the user inputs an invalid value.</param>
		/// <param name="initialValue">The initial dialog value.</param>
		/// <returns>Returns the score, or null if the user cancelled or entered an invalid score.</returns>
		protected int? GetScore(string prompt, string errorMessage, int initialValue)
		{
			int? result = null;

			Generic.InputBox inputDialog = new Wormhole.UI.Application.Controls.Generic.InputBox(prompt);
			inputDialog.Value = initialValue.ToString();

			if (inputDialog.ShowDialog().Value)
			{
				string value = inputDialog.Value;

				try
				{
					result = int.Parse(value);
				}
				catch
				{
					MessageBox.Show("Please enter a valid score.");
					result = null;
				}
			}

			return result;
		}
		#endregion

		#region Get Victory Score
		/// <summary>
		/// Get the victory score from the user.
		/// </summary>
		private void GetVictoryScore()
		{
			int? score = this.GetScore("Please enter the victory total", "Please enter a valid score", this.Player.Score.VictoryTotal);
			if (score != null)
			{
				this.Player.Score.VictoryTotal = score.Value;
			}
		}
		#endregion

		#region Set Glyph Score
		
		#region Get Glyph Score
		/// <summary>
		/// Get the Glyph score from the user.
		/// </summary>
		private void GetGlyphScore()
		{
			int? score = this.GetScore("Please enter the glyph score", "Please enter a valid score", this.Player.Score.GlyphScore);
			if (score != null)
			{
				this.Player.Score.GlyphScore = score.Value;
			}
		}
		#endregion

		#region Increase Glyph Score
		/// <summary>
		/// Increase the glyph score by 1.
		/// </summary>
		private void IncreaseGlyphScore()
		{
			this.Player.Score.GlyphScore++;
		}
		#endregion

		#region Decrase Glyph Score
		/// <summary>
		/// Decrease the glyph score by 1.
		/// </summary>
		private void DecreaseGlyphScore()
		{
			this.Player.Score.GlyphScore--;
		}
		#endregion

		#endregion

		#region Set Experience Score

		#region Get Experience Score
		/// <summary>
		/// Get the experience score from the user.
		/// </summary>
		private void GetExperienceScore()
		{
			int? score = this.GetScore("Please enter the experience score", "Please enter a valid score", this.Player.Score.ExperienceScore);
			if (score != null)
			{
				this.Player.Score.ExperienceScore = score.Value;
			}
		}
		#endregion

		#region Increase Experience Score
		/// <summary>
		/// Increase the experience score by 1.
		/// </summary>
		private void IncreaseExperienceScore()
		{
			this.Player.Score.ExperienceScore++;
		}
		#endregion

		#region Decrease Experience Score
		/// <summary>
		/// Decrease the experience score by 1.
		/// </summary>
		private void DecreaseExperienceScore()
		{
			this.Player.Score.ExperienceScore--;
		}
		#endregion

		#endregion

		#region Set Villian Score

		#region Get Villian Score
		/// <summary>
		/// Get the villian score from the user.
		/// </summary>
		private void GetVillianScore()
		{
			int? score = this.GetScore("Please enter the villian score", "Please enter a valid score", this.Player.Score.VillianScore);
			if (score != null)
			{
				this.Player.Score.VillianScore = score.Value;
			}
		}
		#endregion

		#region Increase Villian Score
		/// <summary>
		/// Increase the villian score by 1.
		/// </summary>
		private void IncreaseVillianScore()
		{
			this.Player.Score.VillianScore++;
		}
		#endregion

		#region Decrease Villian Score
		/// <summary>
		/// Decrease the villian score by 1.
		/// </summary>
		private void DecreaseVillianScore()
		{
			this.Player.Score.VillianScore--;
		}
		#endregion

		#endregion
	}
}
